import React from 'react';
import ReactDom from 'react-dom';

let ThemeContext = React.createContext();


//一个组件什么时候更新：当属性或者状态发生改变的时候
function createContext(initalValue) {
    class Provider extends React.Component {
        //作为静态属性存到Provider的类上，通过类名可以调用到这个属性
        static contextValue = initalValue;   //contextValue不是固定的，可以随便命名

        constructor(props) {
            super(props);
            this.state = {};
            Provider.contextValue = props.value
        }

        //根据props的变化，返回最新的状态对象
        static getDerivedStateFromProps(nextProps, prevState) {
            //更新后的value值赋给contextValue
            Provider.contextValue = nextProps.value;
            return {};   //赋给this.state
        }

        render() {
            return (
                this.props.children
            );
        }
    }

    class Consumer extends React.Component {
        render() {
            return this.props.children(Provider.contextValue);
        }
    }

    return {Provider, Consumer}

}

// let ThemeContext = createContext(null);

//函数组件和类组件混用

class Title extends React.Component {
    static contextType = ThemeContext;   //contextType  react规定的，必须是该变量

    constructor(props, context) {
        super(props);
        // context 就代表上下文对象   ThemeContext.Provider.contextValue = this.context
        //在构造函数里面是不能通过 this.context拿到上下文对象的，只能调参数（context）
        console.log('构造函数context', context)
    }

    render() {
        //context   是一个内部被保护的变量，所以不能直接赋值，但是可以修改个其他名字，比如context2
        // this.context2 = Title.contextType.Provider.contextValue;
        console.log('render ', this.context);
        return (
            //想想如何从provideer里面取到color值
            <div style={{border: `5px solid ${this.context.color}`}}>
                title
            </div>
        );
    }
}


//如果组件Title组件是函数组件：
/*function Title(props) {
    //Consumer:消费者，意思是我要消费上下文（ThemeContext）Provider的value
    return (
        <ThemeContext.Consumer>
            {
                (value) => (
                    <div style={{border: `5px solid ${value.color}`}}>
                        header
                    </div>
                )
            }

        </ThemeContext.Consumer>
    )
}*/


function Header(props) {
    //Consumer:消费者，意思是我要消费上下文（ThemeContext）Provider的value
    return (
        <ThemeContext.Consumer>
            {
                (value) => (
                    <div style={{border: `5px solid ${value.color}`}}>
                        header
                        <Title/>
                    </div>
                )
            }

        </ThemeContext.Consumer>
    )
}

function Content(props) {
    //Consumer:消费者，意思是我要消费上下文（ThemeContext）Provider的value
    return (
        <ThemeContext.Consumer>
            {
                (value) => (
                    <div style={{border: `5px solid ${value.color}`}}>
                        <button onClick={() => value.changeColor('blue')}>change blue</button>
                        <button onClick={() => value.changeColor('red')}>change red</button>
                    </div>
                )
            }

        </ThemeContext.Consumer>
    )
}


function Main(props) {
    //Consumer:消费者，意思是我要消费上下文（ThemeContext）Provider的value
    return (
        <ThemeContext.Consumer>
            {
                (value) => (
                    <div style={{border: `5px solid ${value.color}`}}>
                        main
                        <Content/>
                    </div>
                )
            }
        </ThemeContext.Consumer>
    )
}


class Panel extends React.Component {
    state = {color: 'green'};

    changeColor = (color) => {
        // debugger;
        this.setState({color: color})

    };

    render() {
        let value = {color: this.state.color, changeColor: this.changeColor};
        //Provider提供者，他负责向下层的所有的组件提供数据value:前提是value里面必须包含我们需要的函数或者变量等值，其他组件才可以接收到
        return (
            <ThemeContext.Provider value={value}>
                <div style={{border: `5px solid ${this.state.color}`, width: 500}}>
                    panel
                    <Header/>
                    <Main/>
                </div>
            </ThemeContext.Provider>

        )
    }
}

ReactDom.render(<Panel/>, document.getElementById('root'));


/*
* 问题：如果有多个context，grandContext- >fatherContext -> sonContext
*    grandContext -->ThemeContext
*    fatherContext   --->  fatherContext
* sonContext假如是个函数组件，那么该函数组件在渲染的时候，使用哪个context里面的value属性，不会合并或者覆盖
*
* */
